﻿//-----------------------------------------------------------------------
// <copyright file="MySqlConnection.cs" company="SLWY Enterprises">
// * Copyright (C) 2017 四川商旅无忧科技有限公司 版权所有。
// * version : 1.0
// * author  : qinchaoyue
// * FileName: MySqlConnection.cs
// * history : created by qinchaoyue 2017-10-23 11:38:37
// </copyright>
//-----------------------------------------------------------------------

using System.Collections.Generic;
using System.Data;
using System.Linq;

using Slwy.MySql.Contracts;
using Slwy.MySql.Models;
using Slwy.Utility.Extensions;

namespace Slwy.MySql.Implements
{
    using System;
    using System.Text;

    using Slwy.Context;
    using Slwy.Security.Utility;
    using Slwy.Utility.ConfigurManager;

    /// <inheritdoc />
    /// <summary>
    /// 数据库连接管理
    /// </summary>
    public class MySqlConnection : IMySqlConnection
    {
        /// <summary>
        /// 写连接 key
        /// </summary>
        private const string WriteConnectionKey = "ConnectionWrite";

        /// <summary>
        /// 读连接 key
        /// </summary>
        private const string ReadConnectionKey = "ConnectionRead";

        /// <summary>
        /// 配置节点
        /// </summary>
        private const string ConnectionStringKey = "ConnectionStrings";

        /// <summary>
        /// 配置管理器
        /// </summary>
        private readonly ConfigurHandler _configurHandler;

        public MySqlConnection()
        {
            _configurHandler = new ConfigurHandler();
        }

        /// <summary>
        /// 获取连接字符串
        /// </summary>
        /// <param name="key">连接字符串key</param>
        /// <param name="suffix"> 库名后缀 </param>
        /// <returns>连接字符串</returns>
        private string GetConnectionString(string key, string suffix)
        {
            var connectionString = this._configurHandler.GetAppOptions<List<MConnectionStrings>>(ConnectionStringKey)?.SingleOrDefault(m => m.Name.ToUpper() == key.ToUpper())?.ConnectionString;
            if (connectionString == null)
            {
                throw new ArgumentNullException($"从 {SlwyContext.Current.SettingName} 获取配置节点 {ConnectionStringKey}.{key} 失败, 请确认节点是否存在.");
            }

            return Conn(connectionString, suffix);
        }

        /// <summary>
        /// 获取所有的连接
        /// </summary>
        /// <returns></returns>
        public IList<MConnectionStrings> GetConnections()
        {
            return this._configurHandler.GetAppOptions<List<MConnectionStrings>>(ConnectionStringKey);
        }

        /// <summary>
        /// 获取读连接字符串
        /// </summary>
        /// <param name="suffix"> 库名后缀 </param>
        /// <returns>
        /// 读连接字符串
        /// </returns>
        public string GetReadConnectionString(string suffix = "")
        {
            return this.GetConnectionString(ReadConnectionKey, suffix);
        }

        /// <summary>
        /// 获取写连接字符串
        /// </summary>
        /// <param name="suffix"> 库名后缀 </param>
        /// <returns>写连接字符串</returns>
        public string GetWriteConnectionString(string suffix = "")
        {
            return this.GetConnectionString(WriteConnectionKey, suffix);
        }

        /// <summary>
        /// 获取自定义连接
        /// </summary>
        /// <param name="connectionKey">自定义key</param>
        /// <param name="suffix"> 库名后缀 </param>
        /// <returns>数据库连接</returns>
        public IDbConnection GetCustomeConnection(string connectionKey, string suffix = "")
        {
            var connectionString = this.GetConnectionString(connectionKey, suffix);
            return connectionString.IsNullOrEmpty() ? null : new global::MySql.Data.MySqlClient.MySqlConnection(connectionString);
        }

        /// <summary>
        /// 获取读连接
        /// </summary>
        /// <param name="suffix"> 库名后缀 </param>
        /// <returns>
        /// 数据库连接
        /// </returns>
        public IDbConnection GetReadConnection(string suffix = "")
        {
            var connectionString = this.GetConnectionString(ReadConnectionKey, suffix);
            return connectionString.IsNullOrEmpty() ? null : new global::MySql.Data.MySqlClient.MySqlConnection(connectionString);
        }

        /// <summary>
        /// 获取写连接
        /// </summary>
        /// <param name="suffix"> 库名后缀 </param>
        /// <returns>
        /// 数据库连接
        /// </returns>
        public IDbConnection GetWriteConnection(string suffix = "")
        {
            var connectionString = this.GetConnectionString(WriteConnectionKey, suffix);
            return connectionString.IsNullOrEmpty() ? null : new global::MySql.Data.MySqlClient.MySqlConnection(connectionString);
        }

        /// <summary>
        /// 解密连接字符串
        /// </summary>
        /// <param name="conn"> 原始字符串 . </param>
        /// <param name="suffix"> 库名后缀 . </param>
        /// <returns> 解密后的串 . </returns>
        private static string Conn(string conn, string suffix)
        {
            StringBuilder strBuilder = new StringBuilder();
            string[] connArr = conn.Split(new char[] { ';' });
            foreach (string con in connArr)
            {
                if (con.ToUpper().IndexOf("UID", StringComparison.Ordinal) >= 0 || con.ToUpper().IndexOf("PWD", StringComparison.Ordinal) >= 0)
                {
                    string[] conPwdUser = con.Split(new char[] { '=' });
                    strBuilder.Append(conPwdUser[0]);
                    strBuilder.Append("=");
                    strBuilder.Append(SecurityUtility.DecryptString(conPwdUser[1].Trim()));
                }
                else if (con.ToUpper().IndexOf("DATABASE", StringComparison.Ordinal) >= 0)
                {
                    string[] conDataBase = con.Split(new char[] { '=' });
                    strBuilder.Append(conDataBase[0]);
                    strBuilder.Append("=");
                    strBuilder.Append(conDataBase[1].Trim() + suffix);
                }
                else
                {
                    strBuilder.Append(con);
                }

                strBuilder.Append(";");
            }

            strBuilder.Remove(strBuilder.Length - 1, 1);
            return strBuilder.ToString();
        }
    }
}
